/*
 * @(#)ReportFenster.java
 * 1.0, 2013-01-24
 */
package de.hdm.gruppenkalender.team04.gui;

import de.hdm.gruppenkalender.team04.data.Alarm;
import de.hdm.gruppenkalender.team04.data.Kalender;
import de.hdm.gruppenkalender.team04.data.Kategorie;
import de.hdm.gruppenkalender.team04.data.Person;
import de.hdm.gruppenkalender.team04.data.Termin;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.rmi.RemoteException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;
import java.util.Date;
import javax.swing.JCheckBox;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * Aufbau des ReportFenster mit den diversen Elementen.
 *
 * @author Mathias Bendel (mb167)
 * @author Björn Fichnter (bf023)
 * @author Stefan Hettich (sh176)
 * @author René Kugel (rk044)
 * @author Mark Leonberger (ml072)
 * @author Marta Przybylski (mp070)
 *
 * @version 1.0, 2013-01-24
 *
 */
public class ReportFenster extends JFrame {

    // Name der Anwendung
    private final String APP_NAME = "Gruppenkalender-Verwaltung";
    private final String REPORT = "Report";
    // aktuelle aktiver Nutzer ggf. auch null (Admin)
    private InterfaceClientReport icr = InterfaceClientReport.
            interfaceClientReport();
    // aktuelle aktiver Nutzer ggf. auch null (Admin)
    private Person aktuellerNutzer;
    JPanel hauptPanel = new JPanel();
    //GUI Elemente 
    JButton buttonReportGenerieren;
    JButton buttonReportNeu;
    JSpinner spinnerVon;
    JCheckBox chbVon = new JCheckBox("nach Von-Datum filtern?");
    JSpinner spinnerBis;
    JCheckBox chbBis = new JCheckBox("nach Bis-Datum filtern?");
    JComboBox jcbKategorie;
    JCheckBox chbKategorie = new JCheckBox("nach Kategorie filtern?");
    JComboBox jcbKalender;
    JCheckBox chbKalender = new JCheckBox("nach Kalender filtern?");
    JComboBox jcbPerson;
    JCheckBox chbPerson = new JCheckBox("nach Person filtern?");
    JTextPane jtaReport;
    JScrollPane scrollPaneReport;
    DefaultListModel listModelObjekte = new DefaultListModel();
    // Menü-Items, für den ActionListener-Vergleich
    JMenuBar menueLeiste;
    JMenuItem mItemAusloggen;
    JMenuItem mItemBeenden;
    JLabel titelLabel;
    // HashMaps für die jeweiligen JLists
    HashMap<String, Termin> hashMapTermine;
    HashMap<String, Person> hashMapPerson;
    HashMap<String, Kategorie> hashMapKategorie;
    HashMap<String, Kalender> hashMapKalender;
    HashMap<String, Alarm> hashMapAlarm;

    /**
     * Konstruktor, ohne Parameter setzt KEINE Person und initialisiert somit
     * den "Admin"-Modus
     */
    public ReportFenster() {
        this(null);
    }

    /**
     * Konstruktor, mit Parameter setzt eine Person und initialisiert somit
     * den "Nutzer"-Modus
     *
     * @param   person
     */
    public ReportFenster(Person person) {
        this.aktuellerNutzer = person;
        this.setLocation(30, 30);
        this.erstelleElemente();
    }

    /**
     * @return  Person  aktuellerNutzer
     */
    public Person getAktuellerNutzer() {
        return aktuellerNutzer;
    }

    /**
     * @param   aktuellerNutzer der gesetzt werden soll.
     */
    public void setAktuellerNutzer(Person aktuellerNutzer) {
        this.aktuellerNutzer = aktuellerNutzer;
    }

    /**
     * Erstellt die Elemente und fügt das Haupt-Fenster zusammen.
     */
    public void erstelleElemente() {
        // Prüfen, ob Nutzer gesetzt.
        if (aktuellerNutzer == null) {
            this.setTitle(APP_NAME + " - Administration");
        } else {
            try {
                this.setTitle(APP_NAME + " - '" + aktuellerNutzer.getVorname() +
                        " " + aktuellerNutzer.getNachname() + "'");
            } catch (RemoteException ex) {
                Logger.getLogger(LoginFenster.class.getName()).log(Level.SEVERE,
                        null, ex);
                this.setTitle(APP_NAME + " - <kein Nutzername>");
            }
        }

        // Haupt-Panel zuordnen.
        erstelleHauptPanel();
        this.add(hauptPanel);
        this.erstelleMenuLeiste();

        this.setMinimumSize(new Dimension(800, 600));

        // Anwendung bei Schließen des Fensters beenden.
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Frame packen und anzeigen.
        this.pack();
        this.setVisible(true);
    }

    /**
     * Erstellt die Menü-Leiste
     */
    public void erstelleMenuLeiste() {
        // Menüleiste erzeugen
        menueLeiste = new JMenuBar();

        // erstes Menü erzeugen
        JMenu menueDatei = new JMenu("Datei");

        // erstes Untermenü erzeugen
        String strTempAusloggen = "Abmelden";
        if (this.aktuellerNutzer == null) {
            strTempAusloggen = "Administrator abmelden";
        } else {
            try {
                strTempAusloggen = "'" + aktuellerNutzer.getVorname() + " " +
                        aktuellerNutzer.getNachname() + "' abmelden";
            } catch (RemoteException ex) {
                Logger.getLogger(ReportFenster.class.getName()).log(Level.SEVERE,
                        null, ex);
            }
        }
        mItemAusloggen = new JMenuItem(strTempAusloggen);
        mItemAusloggen.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if (JOptionPane.showConfirmDialog(ReportFenster.this,
                        "Wollen Sie sich wirklich abmelden?", "Abmelden",
                        JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
                    new LoginFenster(false);
                    setVisible(false);
                    dispose();
                }
            }
        });
        menueDatei.add(mItemAusloggen);

        menueDatei.addSeparator();

        mItemBeenden = new JMenuItem("Beenden");
        mItemBeenden.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if (JOptionPane.showConfirmDialog(ReportFenster.this,
                        "Das Programm wirklich beenden?", "Beenden",
                        JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
                    System.exit(0);
                }
            }
        });
        menueDatei.add(mItemBeenden);

        menueLeiste.add(menueDatei);

        this.setJMenuBar(menueLeiste);
    }

    /**
     * Erstellt das Haupt-Panel.
     */
    public void erstelleHauptPanel() {
        hauptPanel.removeAll();

        hauptPanel.setLayout(new BorderLayout());

        // Abstand nach außen erzeugen.
        hauptPanel.setBorder(new EmptyBorder(10, 10, 10, 10));


        JPanel inhaltsPanel = new JPanel();
        inhaltsPanel.setLayout(new GridBagLayout());
        inhaltsPanel.setBorder(new EmptyBorder(10, 10, 10, 10));

        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;
        c.anchor = GridBagConstraints.LINE_START;
        c.insets = new Insets(5, 5, 5, 5);

        c.gridx = 0;
        c.gridy = 0;
        c.gridwidth = 2;
        inhaltsPanel.add(new JLabel("<html><h2>" + REPORT +
                "generator</h2></html>", JLabel.CENTER), c);

        /**
         * JSpinner, JLabel und JCheckBox für "Von"-Datum.
         */
        c.gridx = 0;
        c.gridy = 1;
        c.gridwidth = 1;
        inhaltsPanel.add(new JLabel("Von:"), c);

        spinnerVon = erstelleDateSpinner();

        chbVon.addChangeListener(new ChangeListener() {

            public void stateChanged(ChangeEvent e) {
                if (((JCheckBox) e.getSource()).isSelected()) {
                    spinnerVon.setEnabled(true);
                } else {
                    spinnerVon.setEnabled(false);
                }
            }
        });
        chbVon.setSelected(true);
        c.gridx = 1;
        c.gridy = 1;
        c.gridwidth = 1;
        inhaltsPanel.add(chbVon, c);

        c.gridx = 0;
        c.gridy = 2;
        c.gridwidth = 2;
        inhaltsPanel.add(spinnerVon, c);

        /**
         * JSpinner, JLabel und JCheckBox für "Bis"-Datum.
         */
        c.gridx = 0;
        c.gridy = 3;
        c.gridwidth = 1;
        inhaltsPanel.add(new JLabel("Bis:"), c);

        spinnerBis = erstelleDateSpinner();

        chbBis.addChangeListener(new ChangeListener() {

            public void stateChanged(ChangeEvent e) {
                if (((JCheckBox) e.getSource()).isSelected()) {
                    spinnerBis.setEnabled(true);
                } else {
                    spinnerBis.setEnabled(false);
                }
            }
        });
        chbBis.setSelected(true);
        c.gridx = 1;
        c.gridy = 3;
        c.gridwidth = 1;
        inhaltsPanel.add(chbBis, c);

        c.gridx = 0;
        c.gridy = 4;
        c.gridwidth = 2;
        inhaltsPanel.add(spinnerBis, c);

        /**
         * JComboBox, JLabel und JCheckBox für Kategorie.
         */
        c.gridx = 0;
        c.gridy = 5;
        c.gridwidth = 1;
        inhaltsPanel.add(new JLabel("Kategorie"), c);

        jcbKategorie = erstelleKategorienComboBox();

        chbKategorie.addChangeListener(new ChangeListener() {

            public void stateChanged(ChangeEvent e) {
                if (((JCheckBox) e.getSource()).isSelected()) {
                    jcbKategorie.setEnabled(true);
                } else {
                    jcbKategorie.setEnabled(false);
                }
            }
        });
        if (jcbKategorie.getModel().getSize() != 0) {
            chbKategorie.setSelected(true);
        } else {
            chbKategorie.setSelected(false);
            chbKategorie.setEnabled(false);
        }
        c.gridx = 1;
        c.gridy = 5;
        c.gridwidth = 1;
        inhaltsPanel.add(chbKategorie, c);

        c.gridx = 0;
        c.gridy = 6;
        c.gridwidth = 2;
        inhaltsPanel.add(jcbKategorie, c);

        /**
         * JComboBox, JLabel und JCheckBox für Kalender.
         */
        c.gridx = 0;
        c.gridy = 7;
        c.gridwidth = 1;
        inhaltsPanel.add(new JLabel("Kalender"), c);

        jcbKalender = erstelleKalenderComboBox();

        chbKalender.addChangeListener(new ChangeListener() {

            public void stateChanged(ChangeEvent e) {
                if (((JCheckBox) e.getSource()).isSelected()) {
                    jcbKalender.setEnabled(true);
                } else {
                    jcbKalender.setEnabled(false);
                }
            }
        });
        if (jcbKalender.getModel().getSize() != 0) {
            chbKalender.setSelected(true);
        } else {
            chbKalender.setSelected(false);
            chbKalender.setEnabled(false);
        }
        c.gridx = 1;
        c.gridy = 7;
        c.gridwidth = 1;
        inhaltsPanel.add(chbKalender, c);

        c.gridx = 0;
        c.gridy = 8;
        c.gridwidth = 2;
        inhaltsPanel.add(jcbKalender, c);

        /**
         * JComboBox, JLabel und JCheckBox für Person.
         */
        int gridLayoutParam = 0;
        if (aktuellerNutzer == null) {
            gridLayoutParam = 2;

            c.gridx = 0;
            c.gridy = 9;
            c.gridwidth = 2;
            inhaltsPanel.add(new JLabel("Person"), c);

            jcbPerson = erstellePersonenComboBox();

            chbPerson.addChangeListener(new ChangeListener() {

                public void stateChanged(ChangeEvent e) {
                    if (((JCheckBox) e.getSource()).isSelected()) {
                        jcbPerson.setEnabled(true);
                    } else {
                        jcbPerson.setEnabled(false);
                    }
                }
            });
            if (jcbPerson.getModel().getSize() != 0) {
                chbPerson.setSelected(true);
            } else {
                chbPerson.setSelected(false);
                chbPerson.setEnabled(false);
            }
            c.gridx = 1;
            c.gridy = 9;
            c.gridwidth = 1;
            inhaltsPanel.add(chbPerson, c);

            c.gridx = 0;
            c.gridy = 10;
            c.gridwidth = 2;
            inhaltsPanel.add(jcbPerson, c);
        }

        c.gridx = 0;
        c.gridy = 9 + gridLayoutParam;
        c.gridwidth = 2;
        inhaltsPanel.add(new JLabel("Report"), c);

        buttonReportNeu = new JButton("Neuer Report");
        buttonReportNeu.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                System.out.println("report neu gedrückt");
                erstelleElemente();
                SwingUtilities.updateComponentTreeUI(ReportFenster.this);
                System.out.println("screen neu geladen");
            }
        });

        c.gridx = 0;
        c.gridy = 10 + gridLayoutParam;
        c.gridwidth = 1;
        inhaltsPanel.add(buttonReportNeu, c);

        buttonReportGenerieren = new JButton("Report generieren");
        buttonReportGenerieren.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                Timestamp start = null;
                if (chbVon.isSelected()) {
                    start = berechneTimestamp(spinnerVon.getValue(),
                            true);
                }

                Timestamp ende = null;
                if (chbBis.isSelected()) {
                    ende = berechneTimestamp(spinnerBis.getValue(),
                            false);
                }

                // Gibt an, ob Startzeitpunkt nach Endzeitpunkt liegt.
                boolean startNachEnde = false;

                /**
                 * Die Prüfung, ob Startzeitpunkt nach Endzeitpunkt liegt,
                 * soll nur durchgeführt werden,
                 * wenn weder start noch ende null ist.
                 */
                if (start != null && ende != null) {
                    if (start.after(ende)) {
                        startNachEnde = true;
                    }
                }

                /**
                 * Prüfen, ob startNachEnde <code>false</code> ist,
                 * dann ausführen.
                 *
                 * Wenn start oder ende null ist, wird startNachEnde
                 * automatisch <code>false</code> gesetzt.
                 */
                if (!startNachEnde) {
                    String text = "<html><body><h1>Report wird erstellt..." +
                            "</h1></body></html>";
                    jtaReport.setText(text);



                    try {
                        //Auswahl der Spinner holen
                        /**
                         * Wenn eine Person eingeloggt ist, wird diese übergeben,
                         * sonst wird die Auswahl aus der ComboBox selektiert.
                         */
                        Person gewaehltePerson = aktuellerNutzer;
                        if (aktuellerNutzer == null) {
                            gewaehltePerson = null;
                            if (chbPerson.isSelected()) {
                                gewaehltePerson = hashMapPerson.get(jcbPerson.
                                        getSelectedItem().toString());
                            }
                        }

                        Kategorie gewaehlteKategorie = null;
                        if (chbKategorie.isSelected()) {
                            gewaehlteKategorie = hashMapKategorie.get(
                                    jcbKategorie.getSelectedItem().toString());
                        }

                        Kalender gewaehlterKalender = null;
                        if (chbKalender.isSelected()) {
                            gewaehlterKalender = hashMapKalender.get(
                                    jcbKalender.getSelectedItem().toString());
                        }

                        //Reportgenerieren lassen
                        String reportText = icr.erstelleReport(
                                gewaehltePerson,
                                gewaehlterKalender,
                                gewaehlteKategorie,
                                start,
                                ende);

                        jtaReport.setText(reportText);
                        JOptionPane.showMessageDialog(ReportFenster.this,
                                "Report wurde erfolgreich erstellt.",
                                "Report erstellen",
                                JOptionPane.INFORMATION_MESSAGE);

                    } catch (Exception ex2) {
                        ex2.printStackTrace();
                    }
                } else {
                    JOptionPane.showMessageDialog(ReportFenster.this,
                            "Das Enddatum darf nicht vor dem Startdatum liegen!",
                            "Fehler beim Generieren des Reports",
                            JOptionPane.WARNING_MESSAGE);
                }
            }
        });

        c.gridx = 1;
        c.gridy = 10 + gridLayoutParam;
        c.gridwidth = 1;
        inhaltsPanel.add(buttonReportGenerieren, c);

        jtaReport = erstelleReportTextField();
        scrollPaneReport = new JScrollPane(jtaReport);
        hauptPanel.add(scrollPaneReport, BorderLayout.CENTER);

        hauptPanel.add(inhaltsPanel, BorderLayout.LINE_START);
    }

    /**
     * Erstellt einen neuen JSpinner mit dem aktuellen Zeitpunkt.
     *
     * @return  JSpinner    spinner
     */
    public JSpinner erstelleDateSpinner() {
        JSpinner spinner = new JSpinner(new SpinnerDateModel());
        spinner.setEditor(new JSpinner.DateEditor(spinner,
                "dd.MM.yyyy"));

        Timestamp jetzt = new Timestamp(Calendar.getInstance().getTime().
                getTime());
        spinner.setValue(jetzt);

        return spinner;
    }

    /**
     * Erstellt die ComboBox für die Kategorien-Auswahl.
     *
     * @return  JComboBox   mit Kategorien gefüllt.
     */
    public JComboBox erstelleKategorienComboBox() {

        Vector<Kategorie> kategorien = icr.ermittleAlleKategorien();
        Vector<String> strKategorie = new Vector<String>();
        hashMapKategorie = new HashMap<String, Kategorie>();
        for (Kategorie kategorie : kategorien) {
            try {
                String name = kategorie.ermittleIdentifikationsName();
                strKategorie.add(name);
                hashMapKategorie.put(name, kategorie);
            } catch (RemoteException ex) {
                Logger.getLogger(ReportFenster.class.getName()).
                        log(Level.SEVERE, null, ex);
            }
        }
        JComboBox comboBox = new JComboBox(strKategorie);
        if (kategorien.size() > 0) {
            comboBox.setSelectedIndex(0);
        }

        return comboBox;
    }

    /**
     * Erstellt die Combox-Box zur Kalender-Auswahl.
     *
     * @return  JComboBox   mit Kalender gefüllt.
     */
    public JComboBox erstelleKalenderComboBox() {

        Vector<Kalender> kalenderplural = new Vector<Kalender>();
        if (aktuellerNutzer == null) {
            kalenderplural = icr.ermittleAlleKalender();
        } else {
            kalenderplural = icr.ermittleAlleKalenderVon(aktuellerNutzer);
        }
        Vector<String> strKalender = new Vector<String>();
        hashMapKalender = new HashMap<String, Kalender>();
        for (Kalender kalender : kalenderplural) {
            try {
                String name = kalender.ermittleIdentifikationsName();
                strKalender.add(name);
                hashMapKalender.put(name, kalender);
            } catch (RemoteException ex) {
                Logger.getLogger(ReportFenster.class.getName()).
                        log(Level.SEVERE, null, ex);
            }
        }
        JComboBox comboBox = new JComboBox(strKalender);
        if (kalenderplural.size() > 0) {
            comboBox.setSelectedIndex(0);
        }

        return comboBox;
    }

    /**
     * Erstellt die ComboBox zur Personen-Auswahl (Admin).
     *
     * @return  JComboBox   mit Personen gefüllt.
     */
    public JComboBox erstellePersonenComboBox() {

        Vector<Person> personen = icr.ermittleAllePersonen();
        Vector<String> strPerson = new Vector<String>();
        hashMapPerson = new HashMap<String, Person>();
        for (Person person : personen) {
            try {
                String name = person.ermittleIdentifikationsName();
                strPerson.add(name);
                hashMapPerson.put(name, person);
            } catch (RemoteException ex) {
                Logger.getLogger(ReportFenster.class.getName()).
                        log(Level.SEVERE, null, ex);
            }
        }
        JComboBox comboBox = new JComboBox(strPerson);
        if (personen.size() > 0) {
            comboBox.setSelectedIndex(0);
        }
        return comboBox;
    }

    /**
     * Erstellt das JTextPane für die Anzeige des Reports.
     *
     * @return  JTextPane   textPane für den Report
     */
    public JTextPane erstelleReportTextField() {

        JTextPane textPane = new JTextPane();
        textPane.setEditable(false);
        textPane.setContentType("text/html");
        textPane.setText("<html><body><h1>Hier wird der Report dargestellt." +
                "</h1></body></html>");
        return textPane;
    }

    /**
     * Berechnet anhand des übergebenen Combo-Box Items,
     * den Timestamp des Datums mit Hilfe der Calendar-Klasse.
     *
     * @param   o           Inhalt des Datum-JSpinner.
     * @return  Timestamp   berechnetes Timestamp-Objekt.
     */
    private Timestamp berechneTimestamp(Object o, boolean istStart) {
        Calendar cal = Calendar.getInstance();
        cal.setTime((Date) o);
        if (istStart) {
            // 00:00,00 des gewählten Tages auswählen.
            cal.set(Calendar.HOUR_OF_DAY, 0);
            cal.set(Calendar.MINUTE, 0);
            cal.set(Calendar.SECOND, 0);
            System.out.println(cal.getTime().toString());
        } else {
            // 23:59,59 des gewählten Tages auswählen.
            cal.set(Calendar.HOUR_OF_DAY, 23);
            cal.set(Calendar.MINUTE, 59);
            cal.set(Calendar.SECOND, 59);
            System.out.println(cal.getTime().toString());
        }
        return new Timestamp(cal.getTime().getTime());
    }

    /**
     * Wandelt zwei {@link Timestamp} in einen {@link String} um.
     *
     * @param   start
     * @param   ende
     * @return  String  der Start- und/oder Enddatum beinhaltet.
     */
    public String datumZuString(Timestamp start, Timestamp ende) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm");

        /**
         * Wenn Enddatum leer ist, nur das Startdatum ausgeben.
         */
        if (ende == null) {
            return dateFormat.format(start);
        }
        return dateFormat.format(start) + " - " + dateFormat.format(ende);
    }
}
